package com.tools.db.jdbc;

import com.tools.common.object.Note;

import java.util.Map;
import java.util.Objects;

/**
 * 关系型数据库
 * 的数据源配置
 * 实体对象
 * */
@Note("关系型数据库的数据源配置实体对象")
public class DBSource {

    @Note("数据库驱动全路径")
    private String driverClass;

    @Note("数据库协议 + 路径 + 参数")
    private String url;

    @Note("数据库连接所需的账户名称")
    private String username;

    @Note("数据库连接所需的账户密码")
    private String password;

    @Note("数据库初始化时所创建的连接数")
    private int initialSize = 20;

    @Note("数据库最大活跃的连接数")
    private int maxActive = 100;

    @Note("数据库最小闲置的连接数")
    private int minIdle = 20;

    @Note("连接的最大等待时间，单位毫秒")
    private int maxWait = 20000;

    public DBSource() {}

    public static DBSource of() {
        return new DBSource();
    }

    @Note("读取 properties 里的配置项，转为实例返回")
    public static DBSource from(Map properties, boolean hasApplicationFile) {
        return hasApplicationFile
                ? private_readFromApplicationFile(properties)
                : private_readFromCustomConfigFile(properties);
    }

    public String getDriverClass() {
        if(driverClass == null || driverClass.isEmpty()) throw new IllegalArgumentException("数据源驱动类的全限定类名不能为空");
        return driverClass;
    }

    public void setDriverClass(String driverClass) {
        if(driverClass == null || driverClass.isEmpty()) throw new IllegalArgumentException("不能设置空的数据源驱动类的全限定类名");
        this.driverClass = driverClass;
    }

    public String getUrl() {
        if(url == null || url.isEmpty()) throw new IllegalArgumentException("链接数据源的 url 不能为空");
        return url;
    }

    public void setUrl(String url) {
        if(url == null || url.isEmpty()) throw new IllegalArgumentException("用于连接数据源的 url 不能设置为空");
        this.url = url;
    }

    public String getUsername() {
        if(username == null || username.isEmpty()) throw new IllegalArgumentException("连接数据源所需的用户名不能为空");
        return username;
    }

    public void setUsername(String username) {
        if(username == null || username.isEmpty()) throw new IllegalArgumentException("用于连接数据源所需的用户名不能设置为空");
        this.username = username;
    }

    public String getPassword() {
        if(password == null || password.isEmpty()) throw new IllegalArgumentException("连接数据源所需的密码不能为空");
        return password;
    }

    public void setPassword(String password) {
        if(password == null || password.isEmpty()) throw new IllegalArgumentException("用于连接数据源所需的密码不能设置为空");
        this.password = password;
    }

    public int getInitialSize() {
        return initialSize;
    }

    public void setInitialSize(Integer initialSize) {
        this.initialSize = (initialSize == null || initialSize < 0) ? this.initialSize : initialSize;
    }

    public int getMaxActive() {
        return maxActive;
    }

    public void setMaxActive(Integer maxActive) {
        this.maxActive = (maxActive == null || maxActive < 0) ? this.maxActive : maxActive;
    }

    public int getMinIdle() {
        return minIdle;
    }

    public void setMinIdle(Integer minIdle) {
        this.minIdle = (minIdle == null || minIdle < 0) ? this.minIdle : minIdle;
    }

    public int getMaxWait() {
        return maxWait;
    }

    public void setMaxWait(Integer maxWait) {
        this.maxWait = (maxWait == null || maxWait < 0) ? this.maxWait : maxWait;
    }

    @Override
    public String toString() {
        return "DBSource{" +
                "driverClass='" + driverClass + '\'' +
                ", url='" + url + '\'' +
                ", username='" + username + '\'' +
                ", password='" + password + '\'' +
                ", initialSize=" + initialSize +
                ", maxActive=" + maxActive +
                ", minIdle=" + minIdle +
                ", maxWait=" + maxWait +
                '}';
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DBSource dbSource = (DBSource) o;
        return maxActive == dbSource.maxActive && minIdle == dbSource.minIdle && initialSize == dbSource.initialSize && maxWait == dbSource.maxWait && Objects.equals(driverClass, dbSource.driverClass) && Objects.equals(url, dbSource.url) && Objects.equals(username, dbSource.username) && Objects.equals(password, dbSource.password);
    }

    @Override
    public int hashCode() {
        return Objects.hash(driverClass, url, username, password, maxActive, minIdle, initialSize, maxWait);
    }


    public DBSource driverClass(String driverClass) {
        this.setDriverClass(driverClass);
        return this;
    }

    public DBSource url(String url) {
        this.setUrl(url);
        return this;
    }

    public DBSource username(String username) {
        this.setUsername(username);
        return this;
    }

    public DBSource password(String password) {
        this.setPassword(password);
        return this;
    }

    public DBSource initialSize(Integer initialSize) {
        this.setInitialSize(initialSize);
        return this;
    }

    public DBSource maxActive(Integer maxActive) {
        this.setMaxActive(maxActive);
        return this;
    }

    public DBSource minIdle(Integer minIdle) {
        this.setMinIdle(minIdle);
        return this;
    }

    public DBSource maxWait(Integer maxWait) {
        this.setMaxWait(maxWait);
        return this;
    }

    /* ************************************************************************************************************
     *
     *      私有逻辑
     *
     * ************************************************************************************************************
     * */

    @Note("从 SpringBoot 的 application 配置文件中读取数据源配置")
    private static DBSource private_readFromApplicationFile(Map properties) {
        DBSource dbSource = new DBSource();
        if(properties == null || properties.isEmpty()) return dbSource;
        dbSource.setDriverClass((String) properties.get("spring.datasource.driver-class-name"));
        dbSource.setUrl((String) properties.get("spring.datasource.url"));
        dbSource.setUsername((String) properties.get("spring.datasource.username"));
        dbSource.setPassword((String) properties.get("spring.datasource.password"));
        dbSource.setInitialSize((Integer) properties.get("spring.datasource.druid.initial-size"));
        dbSource.setMaxActive((Integer) properties.get("spring.datasource.druid.max-active"));
        dbSource.setMinIdle((Integer) properties.get("spring.datasource.druid.min-idle"));
        dbSource.setMaxWait((Integer) properties.get("spring.datasource.druid.max-wait"));
        return dbSource;
    }

    @Note("从本工具类的 custom-config.properties 自定义配置文件中读取数据源配置")
    private static DBSource private_readFromCustomConfigFile(Map properties) {
        DBSource dbSource = new DBSource();
        if(properties == null || properties.isEmpty()) return dbSource;
        dbSource.setDriverClass((String) properties.get("db-driver"));
        dbSource.setUrl((String) properties.get("db-url"));
        dbSource.setUsername((String) properties.get("db-username"));
        dbSource.setPassword((String) properties.get("db-password"));
        dbSource.setInitialSize((Integer) properties.get("db-initial-size"));
        dbSource.setMaxActive((Integer) properties.get("db-max-active"));
        dbSource.setMinIdle((Integer) properties.get("db-min-idle"));
        dbSource.setMaxWait((Integer) properties.get("db-max-wait"));
        return dbSource;
    }
}
